/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.azon.guesser.utils;

import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Mahdan Ahmad F A
 */
public class FilledChecker{
    
    public static HashMap doCheck(String chain_code) {
        
        //System.out.println(cekGarisLurus("1111111111111111122222222222222222233333333333333333333333344444444444444444444455555555555555555556666666666666666677777777777777777777778888888888888888999999999999999997777777777777777777777777"));
        
        HashMap<String, String> cache = new HashMap<>();
        
        cache.put("Chain code",    getChainCode(chain_code));
        cache.put("Sequence",      getSequence(chain_code));
        cache.put("Enhanced",      getEnhancedSequence(getSequence(chain_code)));
        cache.put("Position",      getPosition(chain_code));
        cache.put("Titik",         isDotted(chain_code));
        cache.put("Garis Lurus",   "" + cekGarisLurus(getChainCode(chain_code)));
        cache.put("Garis Miring",  "" + cekGarisMiring(getSequence(chain_code)));
        cache.put("Cembung Kanan", "" + cekKurvaCembungKanan(getSequence(chain_code)));
        cache.put("Cembung Kiri",  "" + cekKurvaCembungKiri(getSequence(chain_code)));
        cache.put("Cembung Atas",  "" + cekKurvaCembungAtas(getSequence(chain_code)));
        cache.put("Cembung Bawah", "" + cekKurvaCembungBawah(getSequence(chain_code)));
        return cache;
    }
    
    public void printObjectProperty(String chain_code) {
        String  code        = getChainCode(chain_code);
        int[]   frequency   = getFrequency(chain_code);
        String  sequence    = getSequence(chain_code);
        
        
        System.out.println("Chain code = " + code);
        
        System.out.println("Frekuensi");
        for (int i = 0; i < frequency.length; i++) {
            System.out.println((i + 1) + " = " + frequency[i]);
        }
        System.out.println("");
        System.out.println("Sequence = " + sequence);
        System.out.println(""); // */
    }
    
    private static String isDotted(String chain_code) {
        if (chain_code.contains("titik+")) {
            return "1";
        } else {
            return "0";
        }
    }
    
    private static String getPosition(String chain_code) {
        if (chain_code.contains("+")) {
            return ("(" + chain_code.substring(chain_code.indexOf("+") + 1, chain_code.indexOf("X")) + "," + chain_code.substring(chain_code.indexOf("X") + 1, chain_code.indexOf("Y")) + ")");
        } else {
            return ("(" + chain_code.substring(0, chain_code.indexOf("X")) + "," + chain_code.substring(chain_code.indexOf("X") + 1, chain_code.indexOf("Y")) + ")");
        }
    }
    
    protected static String getChainCode(String chain_code) {
        return givePutty(chain_code.substring(chain_code.indexOf("Y") + 1));
    }
    
    private static int[] getFrequency(String chain_code) {
        int[] frequency = new int[9];
        
        String code = chain_code.substring(chain_code.indexOf("Y") + 1);
        
        for (int i = 0; i < code.length(); i++) {
            frequency[code.charAt(i) - 49]++;
        }
        
        return frequency;
    }
    
    public static String getSequence(String chain_code) {
        String sequence = "";
        
        String code = chain_code.substring(chain_code.indexOf("Y") + 1);
        
        sequence += code.charAt(0);
        for (int i = 1; i < code.length(); i++) {
            if (sequence.charAt(sequence.length() - 1) != code.charAt(i)) {
                sequence += code.charAt(i);
            }
        }
       
        return sequence;
    }
    
    private static String getEnhancedSequence(String sequence) {
        // 12 = A; 14 = B; 32 = C; 36 = D; 74 = E; 78 = F; 96 = G; 98 = H; 
                
        String enhanced     = "";
        String current      = "";
        
        String newSequence  = "XX" + sequence + "XX";

        for (int i = 0; i < newSequence.length(); i++) {
            current = "" + newSequence.charAt(i);
           
            switch(current) {
                case "1":
                    if (newSequence.charAt(i + 1) == '2'){
                        newSequence = getNewSequence(newSequence, i, "12", '3', 'A');
                    } else if (newSequence.charAt(i + 1) == '4') {
                        newSequence = getNewSequence(newSequence, i, "14", '7', 'B');
                    } else {
                        
                    }
                    break;
                case "2":
                    if (newSequence.charAt(i + 1) == '1'){
                        newSequence = getNewSequence(newSequence, i, "21", '4', 'A');
                    } else if (newSequence.charAt(i + 1) == '3') {
                        newSequence = getNewSequence(newSequence, i, "23", '6', 'C');
                    } else {
                        
                    }
                    break; 
                case "3":
                    if (newSequence.charAt(i + 1) == '2'){
                        newSequence = getNewSequence(newSequence, i, "32", '1', 'C');
                    } else if (newSequence.charAt(i + 1) == '6') {
                        newSequence = getNewSequence(newSequence, i, "36", '9', 'D');
                    } else {
                        
                    }
                    break;
                case "4":
                    if (newSequence.charAt(i + 1) == '1'){
                        newSequence = getNewSequence(newSequence, i, "41", '7', 'B');
                    } else if (newSequence.charAt(i + 1) == '7') {
                        newSequence = getNewSequence(newSequence, i, "47", '8', 'E');
                    } else {
                        
                    }
                    break; 
                case "6":
                    if (newSequence.charAt(i + 1) == '3'){
                        newSequence = getNewSequence(newSequence, i, "63", '2', 'D');
                    } else if (newSequence.charAt(i + 1) == '9') {
                        newSequence = getNewSequence(newSequence, i, "69", '8', 'G');
                    } else {
                        
                    }
                    break;
                case "7":
                    if (newSequence.charAt(i + 1) == '4'){
                        newSequence = getNewSequence(newSequence, i, "74", '1', 'E');
                    } else if (newSequence.charAt(i + 1) == '8') {
                        newSequence = getNewSequence(newSequence, i, "78", '9', 'F');
                    } else {
                        
                    }
                    break;
                case "8":
                    if (newSequence.charAt(i + 1) == '7'){
                        newSequence = getNewSequence(newSequence, i, "87", '4', 'F');
                    } else if (newSequence.charAt(i + 1) == '9') {
                        newSequence = getNewSequence(newSequence, i, "89", '6', 'H');
                    } else {
                        
                    }
                    break;
                case "9":
                    if (newSequence.charAt(i + 1) == '6'){
                        newSequence = getNewSequence(newSequence, i, "96", '3', 'G');
                    } else if (newSequence.charAt(i + 1) == '8') {
                        newSequence = getNewSequence(newSequence, i, "98", '7', 'H');
                    } else {
                        
                    }
                    break; 
                default:
                    
                    break;
                    
            }
        }
        
        enhanced = newSequence.substring(2, newSequence.length() - 2);
        
        return enhanced;
    }
    
    private static int cekGarisLurus(String code) {
        int garisLurus = 0;
        int counter = 1;
        
        for(int i = 1; i < code.length(); i++) {
            if (code.charAt(i - 1) == code.charAt(i)) {
                counter++;
            } else {
                if (counter > 5) {
                    garisLurus++;
                }
                counter = 1;
            }
        }
        
        if (counter > 5) {
            garisLurus++;
            counter = 1;
        }

        return garisLurus;
    }
    
    private static int cekGarisMiring(String sequence) {
        int garisMiring = 0;
        
        String enhanced = getEnhancedSequence(sequence);
        
        for (int i = 0; i < enhanced.length(); i++) {
            if ((int)enhanced.charAt(i) > 64) {
                garisMiring++;
            }
        }
        
        int jumlahKurva = (cekKurvaCembungAtas(sequence) + cekKurvaCembungBawah(sequence) + cekKurvaCembungKanan(sequence) + cekKurvaCembungKiri(sequence));
        
        return garisMiring;
    }
    
    private static int cekKurvaCembungKanan(String sequence) {
        int kurvaCembungKanan = 0;
        
        String enhanced    = getEnhancedSequence(sequence);
        String[] letter    = getLetter(enhanced);
        
//        System.out.println(enhanced);
        
        kurvaCembungKanan += runKurva(letter, enhanced, "GHFEDCAB", "987321");
 
        return kurvaCembungKanan;
    }
    
    private static int cekKurvaCembungKiri(String sequence) {
        int kurvaCembungKiri = 0;
        
        String enhanced    = getEnhancedSequence(sequence);
        String[] letter    = getLetter(enhanced);
        
//        System.out.println(enhanced);
        
        kurvaCembungKiri += runKurva(letter, enhanced, "BACDEFHG", "123789");
        
        return kurvaCembungKiri;
        
    }
    
    private static int cekKurvaCembungAtas(String sequence) {
        int kurvaCembungAtas = 0;
        
        String enhanced    = getEnhancedSequence(sequence);
        String[] letter    = getLetter(enhanced);
        
//        System.out.println(enhanced);
        
        kurvaCembungAtas += runKurva(letter, enhanced, "CDGHABEF", "369147");
        
        return kurvaCembungAtas;
        
    }
        
    private static int cekKurvaCembungBawah(String sequence) {
        int kurvaCembungBawah = 0;
        
        String enhanced    = getEnhancedSequence(sequence);
        String[] letter    = getLetter(enhanced);
        
//        System.out.println(enhanced);
        
        kurvaCembungBawah += runKurva(letter, enhanced, "FEBAHGDC", "741963");
        
        return kurvaCembungBawah;
        
    }
    
    private static String getNewSequence(String sequence, int index, String pattern, char another, char subtitution) {
    
        boolean flag = true;
        String  newSequence = "";
        int     counter = 0;
        
        while (flag) {
            if (sequence.substring(index+counter, index+counter+2).equals(pattern)) {
                counter++; counter++;
            } else {
                if (counter >= 4) {
                    if ((sequence.charAt(index+counter) == another)) {
                        counter--;
                    }

                    newSequence = sequence.substring(0,index) + subtitution + sequence.substring(index+counter);
                }
                flag = false;
            }
        }
        
        if (newSequence.isEmpty()) {
            return sequence;
        } else {
            return newSequence;
        }
        
    }
    
    private static String[] getLetter(String enhanced) {
        
        ArrayList<String> letter = new ArrayList<>();

        for (int i = 0; i < enhanced.length(); i++) {
            if ((int)enhanced.charAt(i) > 64) {
                letter.add("" + enhanced.charAt(i) + i);
            }
        }
        
        String[] cache = new String[letter.size()];
        cache = letter.toArray(cache);
        
        return cache;
    }

    private static String getLetterArray(String enhanced) {
        
       String letter = "";

        for (int i = 0; i < enhanced.length(); i++) {
            if ((int)enhanced.charAt(i) > 64) {
                letter += enhanced.charAt(i);
            }
        }

        return letter;
    }
    
    private static String getNextLetter(String[] letter, String current) {
        
        for (int i = 0; i < letter.length - 1; i++) {
            if (letter[i].equals(current)) {
                return letter[i+1];
            }
        }
        
        return "";
    }
    
    private static int getIndexLetter(String[] letter, String current) {
        
        for (int i = 0; i < letter.length; i++) {
            if (letter[i].equals(current)) {
                return i;
            }
        }
        
        return 999;
    }

    private static int cekMiddle (String middle, String contain) {
        int addition = 0;
        
        if ((middle.contains("" + contain.charAt(0))) || (middle.contains("" + contain.charAt(1)))) {
            addition++;
        }
        
        return addition;
    }
    
    private static int cekKurva (String[] letter, String enhanced, int index, String pattern, String infix, char nuisance) {
        int kurva = 0;
        
        char first  = pattern.charAt(0);
        char second = pattern.charAt(1);
        char third  = pattern.charAt(2);
        
        String middle       = "";
        String nextLetter   = getNextLetter(letter, ("" + first +index));
        String letterArray  = getLetterArray(enhanced);
        
        int indexLetter         = getIndexLetter(letter, ("" + first +index));
        int nextLetterPosition  = 0;
        
        if (!(nextLetter.isEmpty())) {
            nextLetterPosition = Integer.parseInt(nextLetter.substring(1));
        }

        if ((letter.length - indexLetter) == 1) { // Index terakhir
            if (letterArray.charAt(0) == third) {
                middle = enhanced.substring(index+1) + enhanced.substring(0, Integer.parseInt(letter[0].substring(1)));
                kurva += cekMiddle(middle, infix);
            } else if ((letterArray.charAt(0) == second) && (letterArray.charAt(1) == third)){
                kurva++;
            }
        } else if ((letter.length - indexLetter) == 2) { // 2 dari belakang
            if (letterArray.charAt(indexLetter+1) == third) {
                middle = enhanced.substring(index+1, nextLetterPosition);
                kurva += cekMiddle(middle, infix);
            } else if ((letterArray.charAt(indexLetter+1) == second) && (letterArray.charAt(0) == third) && (letterArray.charAt(1) != nuisance)){
                kurva++;
            }
        } else {
            if (nextLetter.charAt(0) == third) {
                middle = enhanced.substring(index+1, nextLetterPosition);
                kurva += cekMiddle(middle, infix);
            } else if ((enhanced.length() - index) > 3) {
                if((enhanced.charAt(index+1) == second) && (enhanced.charAt(index+3) == third)){
                    kurva++;
                }
            }
        }
        
        return kurva;
    }

    private static int runKurva (String[] letter, String enhanced, String pattern, String infix) {
        int kurva = 0;
        int prev  = 0;
        
        String order = "";
        
        String first_pattern    = pattern.substring(0,3);
        String second_pattern   = pattern.substring(1,4);
        String third_pattern    = pattern.substring(4,7);
        String fourth_pattern   = pattern.substring(5,8);
        
        String first_infix      = infix.substring(0,2);
        String second_infix     = infix.substring(1,3);
        String third_infix      = infix.substring(3,5);
        String fourth_infix     = infix.substring(4,6);
        
        /*
        System.out.println(first_pattern);
        System.out.println(second_pattern);
        System.out.println(third_pattern);
        System.out.println(fourth_pattern); // */
        
        for (int i = 0; i < enhanced.length(); i++) {
            //System.out.print(i + ". " + enhanced.charAt(i));
            
            if (enhanced.length() - i > 2) {
                order = enhanced.substring(i, i+3);
            } else {
                order = "";
            }
            
            if (enhanced.charAt(i) == first_pattern.charAt(0)) {
                if (order.equals(first_pattern)) {
                    kurva++;
                    i++;
                } else {
                    kurva += cekKurva(letter, enhanced, i, first_pattern, first_infix, second_pattern.charAt(2));
                }
            } else if (enhanced.charAt(i) == second_pattern.charAt(0)) {
                if (order.equals(second_pattern)) {
                    kurva++;
                    i++;
                } else {
                    kurva += cekKurva(letter, enhanced, i, second_pattern, second_infix, 'Z');
                }
            } else if (enhanced.charAt(i) == third_pattern.charAt(0)) {
                if (order.equals(third_pattern)) {
                    kurva++;
                    i++;
                } else {
                    kurva += cekKurva(letter, enhanced, i, third_pattern, third_infix, fourth_pattern.charAt(2));
                }
            } else if (enhanced.charAt(i) == fourth_pattern.charAt(0)) {
                if (order.equals(fourth_pattern)) {
                    kurva++;
                    i++;
                } else {
                    kurva += cekKurva(letter, enhanced, i, fourth_pattern, fourth_infix, 'Z');
                }
            } else {
                
            }
            
            /*
            if (prev == kurva) {
                System.out.println("");
            } else {
                System.out.println("<-- gotcha");
                prev++;
            } // */
            
        }
        
        return kurva;
    }
    
    private static String givePutty(String code) {
        String patched = code;
        
        char current;
        char accused;
        
        for (int i = 0; i < patched.length() - 3; i++) {
            current = patched.charAt(i);
            accused = patched.charAt(i+3);
            
            if ((current == accused) && (cekAcne(patched.substring(i+1, i+3)))) {
                patched = patched.substring(0,i) + current + patched.substring(i+3);
            }
        }
        
        return patched;
    }
    
    private static boolean cekAcne(String accused) {
        switch (accused) {
            case "71":
                return true;
            case "39":
                return true;
            case "13":
                return true;
            case "97":
                return true;
            default:
                return false;
        }
        
        
    }
}
